﻿using HtmlAgilityPack;
using Microsoft.WindowsAPICodePack.Dialogs;
using Microsoft.Xaml.Behaviors.Layout;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Services.Dialogs;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Media;
using System.Xml.Serialization;
using TestLogRealtimeMonitor.Common;
using TestLogRealtimeMonitor.Helper;
using TestLogRealtimeMonitor.Helpers;
using TestLogRealtimeMonitor.Infrastructures;
using TestLogRealtimeMonitor.Models;

namespace TestLogRealtimeMonitor.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        //日志的类型
        enum LogType
        {
            Success = 0,
            Error = 1
        }
        private Regex regTargetFile;
        private FileListenerServer listenerServer;//监听服务
        private IDialogService dialogService;
        public MainWindowViewModel(IDialogService dialogServiceParam)
        {
            dialogService = dialogServiceParam;
        }

        #region 属性
        private string selectedProductFullPath;
        /// <summary>
        /// 选择的产品
        /// </summary>
        public string SelectedProductFullPath
        {
            get { return selectedProductFullPath; }
            set { selectedProductFullPath = value; }
        }

        private string appStatus;
        /// <summary>
        /// 程序的状态信息
        /// </summary>
        public string AppStatus
        {
            get { return appStatus; }
            set { SetProperty(ref appStatus, value); }
        }
        private int passCount;
        /// <summary>
        /// 通过的数量
        /// </summary>
        public int PassCount
        {
            get { return passCount; }
            set { SetProperty(ref passCount, value); }
        }
        private int failCount;
        /// <summary>
        /// 未通过的数量
        /// </summary>
        public int FailCount
        {
            get { return failCount; }
            set { SetProperty(ref failCount, value); }
        }
        private string monitorFolder;
        /// <summary>
        /// 监视的目录
        /// </summary>
        public string MonitorFolder
        {
            get { return monitorFolder; }
            set { SetProperty(ref monitorFolder, value); }
        }
        private Brush logForeground;
        /// <summary>
        /// 过程信息的文本
        /// </summary>
        public Brush LogForeground
        {
            get { return logForeground; }
            set { SetProperty(ref logForeground, value); }
        }
        private string log;
        /// <summary>
        /// 过程信息
        /// </summary>
        public string Log
        {
            get { return log; }
            set { SetProperty(ref log, value); }
        }
        #endregion

        #region 命令
        private DelegateCommand loadPageCmd;
        public DelegateCommand LoadPageCmd =>
            loadPageCmd ?? (loadPageCmd = new DelegateCommand(LoadedPage));

        private DelegateCommand browserCmd;
        /// <summary>
        /// 浏览目录命令
        /// </summary>
        public DelegateCommand BrowserCmd =>
            browserCmd ?? (browserCmd = new DelegateCommand(ExecuteBrowser));


        #endregion

        #region 方法
        //页面加载
        void LoadedPage()
        {
            var products = FetchProducts();
            var dialogParams = new DialogParameters { { "Products", products } };
            dialogService.ShowDialog("SelectProduct", dialogParams, r =>
            {
                //结果是OK
                if (r.Result == ButtonResult.OK)
                {
                    SelectedProductFullPath = r.Parameters.GetValue<string>("SelectedProductFullPath");
                    //加载产品的配置信息
                    Task.Run(() =>
                    {
                        Global.ProductConfiguration =BusinessProcess.DeserializeFromXml<ConfigInfo>(SelectedProductFullPath);
                        regTargetFile=new Regex(Global.ProductConfiguration.TargetFileFormat, RegexOptions.Compiled);
                    });
                }
                //结果是取消或者没有选择
                else if (r.Result == ButtonResult.None || r.Result == ButtonResult.Cancel)
                {

                }

            });
        }
        /// <summary>
        /// 检索产品
        /// </summary>
        /// <returns></returns>
        private Dictionary<string, string> FetchProducts()
        {
            var products = new Dictionary<string, string>();
            var productFolder = Path.Combine(Environment.CurrentDirectory, "Product");
            var dirProduct = new DirectoryInfo(productFolder);
            var fiProducts = dirProduct.GetFiles("*.cfg", SearchOption.AllDirectories);
            var productName = string.Empty;
            var productFullPath = string.Empty;
            foreach (var fiProduct in fiProducts)
            {
                productName = Path.GetFileNameWithoutExtension(fiProduct.FullName);
                productFullPath = fiProduct.FullName;
                if (!products.Keys.Contains(productName))
                {
                    products.Add(productName, productFullPath);
                }
            }
            return products;
        }
        /// <summary>
        /// 浏览监控的路径信息
        /// </summary>
        private void ExecuteBrowser()
        {
            listenerServer?.Stop();
            CommonOpenFileDialog dialog = new CommonOpenFileDialog();
            dialog.IsFolderPicker = true;
            var dialogResult = dialog.ShowDialog();
            if (dialogResult == CommonFileDialogResult.Ok)
            {
                MonitorFolder = dialog.FileName;
                listenerServer = new FileListenerServer(MonitorFolder, ResolveFile);
                listenerServer.Start();
            }
        }
        /// <summary>
        /// 解析文件
        /// </summary>
        /// <param name="path">文件路径</param>
        private void ResolveFile(string path)
        {
            try
            {
                string fileName = Path.GetFileName(path);
                AppStatus = string.Format($"发现文件【{fileName}】");
                //如果不是目标文件格式直接跳过
                if (!regTargetFile.IsMatch(fileName))
                {
                    AppStatus = "不是目标格式文件";
                    return;
                }

                //获取电脑名
                string computerName = Environment.MachineName;
                var fileinfo = new FileInfo(path);
                string fileCreateDate = fileinfo.LastWriteTime.ToString("yyyyMMddHHmmss");
                AppStatus = string.Format($"开始处理文件【{fileName}】");
                //处理本地HTML文档

                var document = new HtmlDocument();
                document.Load(path,Encoding.UTF8);
                var bodyElement = document.DocumentNode.SelectSingleNode("//body");
                var bodyInnerText = bodyElement.InnerText;
                var sqlResultModel = new SqlResultEntity();
                var bodyInnerTextComponents = bodyInnerText.Split(new char[] { '\r', '\n' });
                sqlResultModel.QRCode = bodyInnerTextComponents.FirstOrDefault(c => c.Contains("Serial Number:"))?.Replace("Serial Number:", "")?.Trim();
                sqlResultModel.ChipID = bodyInnerTextComponents.FirstOrDefault(c => c.Contains("UID:"))?.Replace("UID:", "")?.Trim();
                sqlResultModel.Result = bodyInnerTextComponents.FirstOrDefault(c => c.Contains("Test Result:"))?.Replace("Test Result:", "")?.Trim();
                sqlResultModel.Other = string.Join("|", bodyInnerTextComponents);
                sqlResultModel.FileName = string.Format($"{path}|{computerName}").Length > 200 ? string.Format($"{path}|{computerName}").Substring(0, 200) : string.Format($"{path}|{computerName}");
                //保存到数据库中
                if (Global.ProductConfiguration.IsUpload)
                {
                    AppStatus = "开始上传数据库...";
                    bool isSaveSuccess = false;
                    //是否要上传到TestTracking表里面
                    if (Global.ProductConfiguration.IsUploadTestTracking)
                    {
                        isSaveSuccess = BusinessProcess.SaveTestTracking(sqlResultModel);
                    }
                    //是否要上传到TestLog表里面
                    if (Global.ProductConfiguration.IsUploadTestLog)
                    {
                        isSaveSuccess = BusinessProcess.SaveTestLog(sqlResultModel);
                    }
                    //上传失败显示在界面
                    if (!isSaveSuccess)
                    {
                        AddLog(LogType.Error, string.Format("{0}--上传失败", fileName));
                        AppStatus = "上传数据库失败";
                    }
                    else
                    {
                        if (sqlResultModel.Result.ToUpper() == "PASS")
                        {
                            PassCount += 1;
                        }
                        else
                        {
                            FailCount += 1;
                        }
                        AddLog(LogType.Success, fileName);
                        AppStatus = string.Format($"{fileName}处理完成");
                    }
                }

            }
            catch (Exception ex)
            {
                LogHelper.WriteLog(ex.Message, ex);
                throw new Exception(ex.Message);
            }
        }
        private void AddLog(LogType type, string log)
        {
            switch (type)
            {
                case LogType.Success:
                    Application.Current.Dispatcher.BeginInvoke((Action)(() =>
                    {
                        LogForeground = Brushes.Green;
                        Log = string.Format(">>>{0}:{1}", DateTime.Now.ToString("HHmmss"), log);
                    }));
                    break;
                case LogType.Error:
                    Application.Current.Dispatcher.BeginInvoke((Action)(() =>
                    {
                        LogForeground = Brushes.Red;
                        Log = string.Format(">>>{0}:{1}", DateTime.Now.ToString("HHmmss"), log);
                    }));
                    break;
                default:
                    break;
            }
        }
        #endregion
    }
}
